﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Net;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using com.lover.astd.common.manager;
using com.lover.common;

namespace com.lover.astd.game.ui
{
    public partial class ReportViewer : Form
    {
        private string _rawText = "";
        private List<List<ArmyInfo>> _steps = new List<List<ArmyInfo>>();
        private int _currentStep = 0;
        public ReportViewer()
        {
            InitializeComponent();
        }
        public void setReport(string url)
        {
            txt_url.Text = url;
            openUrl(url);
        }
        private void ReportViewer_Load(object sender, EventArgs e)
        {
            foreach (Control control in this.Controls)
            {
                if (control.Name.StartsWith("panel_") || control.Name == "lbl_result") control.Visible = false;
            }
        }
        private class ArmyInfo
        {
            public string name;
            public int level;
            public int armyNow;
            public int armyMax;
            public int moracle;
            public string status;
            /// <summary>
            /// 0=不受影响, 1=攻击方, 2=防守方
            /// </summary>
            public int action_target;

            public ArmyInfo Clone()
            {
                ArmyInfo info = new ArmyInfo();
                info.name = this.name;
                info.level = this.level;
                info.armyNow = this.armyNow;
                info.armyMax = this.armyMax;
                info.moracle = this.moracle;
                info.status = this.status;
                info.action_target = this.action_target;
                return info;
            }
        }

        private void btn_openUrl_Click(object sender, EventArgs e)
        {
            if (txt_url.Text == "")
            {
                UiUtils.getInstance().info("还未输入网址");
                return;
            }
            string url = txt_url.Text;
            openUrl(url);
        }
        private void openUrl(string url)
        {
            if (url.IndexOf("?fid=") >= 0)
            {
                url = url.Replace("?fid=", "root/fight.action?id=");
            }
            CookieContainer cook_container = new CookieContainer(10000, 1000, 409600);
            if (web_view != null && web_view.Document != null)
            {
                string cookies = web_view.Document.Cookie;
                if (cookies != null)
                {
                    cookies = cookies.Replace(';', ',');
                    cook_container.SetCookies(new Uri(txt_url.Text), cookies);
                }
            }
            List<Cookie> game_cookies = new List<Cookie>();
            CookieCollection cooks = cook_container.GetCookies(new Uri(url));
            foreach (Cookie cc in cooks) game_cookies.Add(cc);
            _rawText = TransferMgr.doGet(url, ref game_cookies);
            initContents();
        }
        private void btn_openFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.CheckFileExists = true;
            DialogResult result = dlg.ShowDialog();
            if (result != DialogResult.OK) return;

            FileStream instream = new FileStream(dlg.FileName, FileMode.Open);

            string retstr = "";
            try
            {
                StreamReader reader = new StreamReader(instream);
                retstr = reader.ReadToEnd();
                // remove the first 3 utf-8 BOM char (EF BB BF)
                retstr = retstr.Substring(retstr.IndexOf("<results>"));

                _rawText = retstr;

                initContents();
            }
            catch (Exception ex)
            {
                UiUtils.getInstance().info("出错了, " + ex.Message);
            }
            finally
            {
                instream.Close();
            }
        }

        private void initContents()
        {
            if (_rawText == null || _rawText == "")
            {
                UiUtils.getInstance().info("打开失败, 请检查是否有误");
                return;
            }
            _currentStep = 0;
            _steps.Clear();

            try
            {
                XmlDocument xml = new XmlDocument();
                xml.LoadXml(_rawText);

                // build steps
                XmlNode rawReport_node = xml.SelectSingleNode("/results/battlereport/report");
                if (rawReport_node == null)
                {
                    UiUtils.getInstance().info("您所查看的战报不存在或已经过期");
                    return;
                }
                string rawReport = rawReport_node.InnerText;
                string[] reportArray = rawReport.Split(';');
                int total_steps = reportArray.Length - 2;

                List<ArmyInfo> init_armys = new List<ArmyInfo>();

                string summary_attacker = reportArray[0];
                string[] army_attacker = summary_attacker.Split('|');
                // 前三项没用
                ArmyInfo tmpinfo = null;
                for (int i = 3, len = army_attacker.Length; i < len; i++)
                {
                    string raw = army_attacker[i];
                    switch ((i-3) % 5)
                    {
                        case 0:
                            if (tmpinfo != null)
                            {
                                init_armys.Add(tmpinfo);
                            }
                            tmpinfo = new ArmyInfo();
                            tmpinfo.moracle = 0;
                            tmpinfo.status = "";
                            tmpinfo.name = raw;
                            break;
                        case 1:
                            tmpinfo.level = Int32.Parse(raw);
                            break;
                        case 2:
                            // 这里表示该部队的图片id
                            break;
                        case 3:
                            tmpinfo.armyNow = Int32.Parse(raw);
                            break;
                        case 4:
                            tmpinfo.armyMax = Int32.Parse(raw);
                            break;
                    }
                }
                init_armys.Add(tmpinfo);

                string summary_defender = reportArray[1];
                string[] army_defender = summary_defender.Split('|');
                tmpinfo = null;
                for (int i = 3, len = army_defender.Length; i < len; i++)
                {
                    string raw = army_defender[i];
                    switch ((i - 3) % 5)
                    {
                        case 0:
                            if (tmpinfo != null)
                            {
                                init_armys.Add(tmpinfo);
                            }
                            tmpinfo = new ArmyInfo();
                            tmpinfo.moracle = 0;
                            tmpinfo.status = "";
                            tmpinfo.name = raw;
                            break;
                        case 1:
                            tmpinfo.level = Int32.Parse(raw);
                            break;
                        case 2:
                            // 这里表示该部队的图片id
                            break;
                        case 3:
                            tmpinfo.armyNow = Int32.Parse(raw);
                            break;
                        case 4:
                            tmpinfo.armyMax = Int32.Parse(raw);
                            break;
                    }
                }
                init_armys.Add(tmpinfo);
                for (int i = 0; i < total_steps; i++)
                {
                    // do action for this step
                    string step_desc = reportArray[2 + i]; // 前2个是攻防的summary, 所以要2+i
                    if (step_desc == "") break;
                    // clear all armies' status
                    for (int j = 0; j < 18; j++)
                    {
                        init_armys[j].status = "";
                        init_armys[j].action_target = 0;
                    }
                    string[] step_desc_array = step_desc.Split('|');
                    string action_summary = step_desc_array[0];
                    int action_position = Int32.Parse(step_desc_array[1]);
                    int action_target = 0;
                    string action_type = "";
                    string action_number_str = "";
                    if(step_desc_array[0] != "Init" && step_desc_array[0] != "状态")
                    {
                        action_target = Int32.Parse(step_desc_array[2]);
                        action_type = step_desc_array[3];
                    }
                    else
                    {
                        action_type = step_desc_array[2];
                        action_number_str = step_desc_array[3];
                    }
                    
                    // 设置动作的army属性
                    ArmyInfo action_army = init_armys[getArmyIndex(action_position)];
                    action_army.action_target = 1;
                    if (action_type == "治疗")
                    {
                        action_army.status = "治疗";
                    }
                    else
                    {
                        action_army.status = String.Format("{0} {1} {2}", action_summary, action_type, action_number_str);
                        if (action_type == "士气")
                        {
                            action_army.moracle += Int32.Parse(action_number_str);
                        }
                        else if(action_type == "伤害")
                        {
                            action_army.armyNow -= Int32.Parse(action_number_str);
                        }
                    }

                    // 从数组第5个元素开始, 每3个为对一个army的影响, 第一个是army的position, 第二个是影响的类型, 第三个是影响的具体数值
                    int target_army_position = 0;
                    string target_effect_type = "";
                    int target_effect_number = 0;
                    for (int j = 4, len_j = step_desc_array.Length; j < len_j; j++)
                    {
                        switch ((j - 4) % 3)
                        {
                            case 0:
                                target_army_position = Int32.Parse(step_desc_array[j]);
                                break;
                            case 1:
                                target_effect_type = step_desc_array[j];
                                break;
                            case 2:
                                // 数据获取完毕, 开始输入
                                ArmyInfo targetarmy = init_armys[getArmyIndex(target_army_position)];
                                if(targetarmy.action_target == 0) targetarmy.action_target = 2;
                                if (target_effect_type == "伤害")
                                {
                                    target_effect_number = Int32.Parse(step_desc_array[j]);
                                    targetarmy.armyNow -= target_effect_number;
                                    targetarmy.status += String.Format("兵力减少{0}↓  ", target_effect_number);
                                }
                                else if(target_effect_type == "士兵")
                                {
                                    target_effect_number = Int32.Parse(step_desc_array[j]);
                                    targetarmy.armyNow += target_effect_number;
                                    targetarmy.status += String.Format("兵力增加{0}↑  ", target_effect_number);
                                }
                                else if (target_effect_type == "士气")
                                {
                                    target_effect_number = Int32.Parse(step_desc_array[j]);
                                    if (action_type == "鼓舞")
                                    {
                                        targetarmy.status += String.Format("士气增加{0}↑  ", target_effect_number);
                                        targetarmy.moracle += target_effect_number;
                                    }
                                    else
                                    {
                                        targetarmy.status += String.Format("士气变成{0}  ", target_effect_number);
                                        targetarmy.moracle = target_effect_number;
                                    }
                                }
                                else if (target_effect_type == "士气减少")
                                {
                                    target_effect_number = Int32.Parse(step_desc_array[j]);
                                    targetarmy.status += String.Format("士气减少{0}↓  ", target_effect_number);
                                    targetarmy.moracle -= target_effect_number;
                                }
                                else if (target_effect_type == "失败")
                                {
                                    targetarmy.status += String.Format("{0}失败  ", action_type);
                                }
                                else
                                {
                                    targetarmy.status += string.Format("{0}  ", target_effect_type);
                                    bool result = Int32.TryParse(step_desc_array[j], out target_effect_number);
                                    if (result)
                                    {
                                        targetarmy.armyNow -= target_effect_number;
                                        targetarmy.status += String.Format("兵力减少{0}↓  ", target_effect_number);
                                    }
                                    else
                                    {
                                        targetarmy.status += String.Format("{0}{1}  ", target_effect_type, step_desc_array[j]);
                                    }
                                }
                                break;
                        }
                    }

                    // save action to step
                    List<ArmyInfo> tmpstep = new List<ArmyInfo>();
                    for (int j = 0, len = init_armys.Count; j < len; j++)
                    {
                        tmpstep.Add(init_armys[j].Clone());
                    }
                    _steps.Add(tmpstep);
                }

                // render result
                // init username and weapon info
                lbl_attacker.Text = String.Format("{0} ({1}级)", xml.SelectSingleNode("/results/attacker/playername").InnerText, xml.SelectSingleNode("/results/attacker/playerlevel").InnerText);
                lbl_defender.Text = String.Format("{0} ({1}级)", xml.SelectSingleNode("/results/defender/playername").InnerText, xml.SelectSingleNode("/results/defender/playerlevel").InnerText);
                lbl_result.Text = xml.SelectSingleNode("/results/battlereport/winside").InnerText == "1" ? "攻方胜" : "守方胜";
                lbl_result.Visible = true;
                // render weapon info
                XmlNode attacker_weapon_node = xml.SelectSingleNode("/results/battlereport/troopequipinfofrom");
                if (attacker_weapon_node != null)
                {
                    lbl_attackerWeapon.Text = getWeaponInfo(attacker_weapon_node.InnerText);
                }

                XmlNode defender_weapon_node = xml.SelectSingleNode("/results/battlereport/troopequipinfoto");
                if (defender_weapon_node != null)
                {
                    lbl_defenderWeapon.Text = getWeaponInfo(defender_weapon_node.InnerText);
                }

                //enable action buttons
                btn_init.Enabled = btn_prev.Enabled = btn_next.Enabled = btn_result.Enabled = true;

                // start render
                renderCurrentStep();
            }
            catch (System.Exception ex)
            {
                UiUtils.getInstance().info("解析数据出错, 请检查是否有误, " + ex.Message);
            }
            finally
            {
            }
        }
        private string getWeaponInfo(string raw)
        {
            string result = "";
            string[] raw_array = raw.Split(',');
            for (int i = 0, len = raw_array.Length; i < len; i++)
            {
                if (raw_array[i] == "") continue;
                string[] info_array = raw_array[i].Split('|');
                result += String.Format("{0}({1})  ", info_array[3].Substring(info_array[3].Length-1), info_array[1]);
            }
            return result;
        }
        private int getArmyIndex(int armyPostion)
        {
            if (armyPostion < 20)  // 是攻方, 对应init_armys中的0-8
            {
                return armyPostion - 11;
            }
            else // 是守方, 对应init_armys中的9-17
            {
                return armyPostion - 21 + 9;
            }
        }
        private void renderCurrentStep()
        {
            lbl_steps.Text = String.Format("{0}/{1}", _currentStep+1, _steps.Count);
            if (_currentStep > _steps.Count - 1) return;
            List<ArmyInfo> stepInfo = _steps[_currentStep];
            for (int i = 0, len = stepInfo.Count; i < len; i++)
            {
                // 0-8 is attacker, 9-17 is defender
                if (i <= 8) renderArmy(11 + i, stepInfo[i]);
                else renderArmy(21 + i - 9, stepInfo[i]);
            }
        }
        private void renderArmy(int armyPosition, ArmyInfo info)
        {
            Panel panel = this.Controls.Find("panel_" + armyPosition, true)[0] as Panel;
            if (info.armyNow == 0 && info.action_target == 0)
            {
                panel.Visible = false;
                return;
            }
            panel.Visible = true;
            if (info.action_target == 0)
            {
                // clear select status
                panel.BackColor = System.Drawing.SystemColors.Control;
            }
            else if (info.action_target == 1)
            {
                // clear select status
                panel.BackColor = System.Drawing.Color.PeachPuff;
            }
            else
            {
                // add select status
                panel.BackColor = System.Drawing.Color.Silver;
            }
            Label lbl_name = this.Controls.Find("lbl_name_" + armyPosition, true)[0] as Label;
            Label lbl_level = this.Controls.Find("lbl_level_" + armyPosition, true)[0] as Label;
            Label lbl_army = this.Controls.Find("lbl_army_" + armyPosition, true)[0] as Label;
            Label lbl_moracle = this.Controls.Find("lbl_moracle_" + armyPosition, true)[0] as Label;
            Label lbl_status = this.Controls.Find("lbl_status_" + armyPosition, true)[0] as Label;

            lbl_name.Text = info.name;
            lbl_level.Text = String.Format("级:{0}", info.level);
            lbl_army.Text = String.Format("兵:{0}/{1}", info.armyNow, info.armyMax);
            lbl_moracle.Text = String.Format("士:{0}", info.moracle);
            lbl_status.Text = info.status;
        }

        private void btn_saveFile_Click(object sender, EventArgs e)
        {
            if (_rawText == null || _rawText == "")
            {
                UiUtils.getInstance().info("还没输入文件或网址呢");
                return;
            }
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.CreatePrompt = true;
            DialogResult result = dlg.ShowDialog();
            if (result != DialogResult.OK) return;

            Stream stream = dlg.OpenFile();
            StreamWriter wr = new StreamWriter(stream);
            wr.Write(_rawText);
            wr.Flush();
            wr.Close();
        }

        private void btn_init_Click(object sender, EventArgs e)
        {
            _currentStep = 0;
            renderCurrentStep();
        }

        private void btn_prev_Click(object sender, EventArgs e)
        {
            if (_currentStep > 0)
            {
                _currentStep--;
                renderCurrentStep();
            }
        }

        private void btn_next_Click(object sender, EventArgs e)
        {
            if (_currentStep < _steps.Count - 1)
            {
                _currentStep++;
                renderCurrentStep();
            }
        }

        private void btn_result_Click(object sender, EventArgs e)
        {
            _currentStep = _steps.Count - 1;
            renderCurrentStep();
        }
    }
}
